package adoper

import (
	"fmt"
	"strconv"
	"strings"
	"sync"
	"time"

	"advertoper/db"

	"github.com/astaxie/beego"
	log "github.com/cihub/seelog"
)

var (
	items   map[int]interface{}
	layouts map[string]LayoutSeq

	maxid int64

	upItems   map[int]interface{}
	upLayouts map[string]LayoutSeq

	MyLock *sync.RWMutex
)

type LayoutSeq map[int]string

const (
	ANDROID               = "ff983cecc76d406a8b1c7c3c1b7cd172"
	IOS                   = "cc0dec8c07444e9dadb75d41218c4fe4"
	TV                    = "tv"
	ANDROID_INTERNATIONAL = "c44f8e3c36d4c13bef44ee10330833a"
	IOS_INTERNATIONAL     = "cdbf8dac2fd34f2e999a98cfd66c3c3d"
	AERADISTRICTION       = "jdxg_sz_4"
	QK_ANDROID            = "9c9babfb8a3f4bb48d4ea651368585f2"
	QK_IOS                = "4a25a6e2719648789640f9254dd862a9"
	QK_H5                 = "585d035ae9584f0f84ce6aa1500ed2ab"
)

const (
	ALL_AREA    = "0000"
	ALL_VERSION = "0000"
	ALL_CHANNEL = "0000"
	SEP         = "$"
)

const (
	EFFECT = 1
)

/*
	Body的额外参数内容
*/
type ReqExtraParam struct {
	ClientIp    string
	AppKey      string
	PicSize     string `json:"pic_size"`
	Channel     string `json:"channel"`
	Model       string `json:"model"`
	MobileOS    string `json:"os"`
	Vuid        string `json:"vuid"`
	VersionCode int    `json:"version_code"`
	Pos         int64  `json:"pos"`
}

type BASE struct { //公共信息
	Position    int   `json:"position"`
	ItemType    int64 `json:"type"`
	Start_tick  int64 `json:"start_tick"`
	End_tick    int64 `json:"end_tick"`
	Weight      int64 `json:"weight"`
	id          int
	region      string
	versionCode string
	channel     string
}
type CLICK struct { //是否可点击信息
	Clickable int64                  `json:"clickable"`
	Action    int64                  `json:"action"`
	Args      map[string]interface{} `json:"args"`
}
type TEXT struct {
	BASE
	CLICK
	Router  string `json:"router"`
	Content string `json:"text"`
	Color   int64  `json:"color"`
}
type URL struct {
	Pic_url string `json:"url"`
	Size    string `json:"size"`
}
type IMG struct {
	BASE
	CLICK
	Router string `json:"router"`
	Urls   []*URL `json:"urls"`
	tag    int    //标记参数错误的图片，直接忽略
}
type WEB struct {
	BASE
	Router string `json:"router"`
	Url    string `json:"url"`
}
type JSON struct { //临时增加TV运营位
	//	Position int64       `json:"position"`
	BASE
	Data map[string]interface{} `json:"data"`
}

func init() {
	maxid = 0

	items = make(map[int]interface{})
	layouts = make(map[string]LayoutSeq)

	upItems = make(map[int]interface{})
	upLayouts = make(map[string]LayoutSeq)
	MyLock = new(sync.RWMutex)

	upMemory()
	go periodupMemory()

}

func upMemory() {
	maxid = getMaxid()
	getLayoutInfo()
	getItemInfo()
	//log.Debugf("info:%s\n, %s\n", layouts, items)
}

func periodupMemory() {
	reloadInterval := beego.AppConfig.DefaultInt("reloadAdvertisementOperation", 60)
	interval := time.Second * time.Duration(reloadInterval)
	t1 := time.NewTimer(interval)
	for {
		select {
		case <-t1.C:
			upMemory()
			t1.Reset(interval)
		}
	}
}

func getLayoutInfo() { //appkey--position--seq
	mysqlHelper := db.GetMysqlHelper()
	sql := "select appkey, position, layout from advert_layout where status = ?"
	results, err := mysqlHelper.Query(sql, EFFECT)
	if err != nil {
		log.Warnf("sql err, sql:%s, err:%s", sql, err.Error())
		return
	}
	if (len(results) == 0) || (results == nil) {
		return
	}
	for _, dt := range results {
		appkey := string(dt["appkey"].([]byte))
		if _, ok := upLayouts[appkey]; !ok {
			upLayouts[appkey] = make(LayoutSeq)
		}
		posMap := upLayouts[appkey]

		pos := dt["position"].(int64)
		seq := string(dt["layout"].([]byte))
		posMap[int(pos)] = seq
	}

	MyLock.Lock()
	layouts = upLayouts
	MyLock.Unlock()

	upLayouts = make(map[string]LayoutSeq)
}

func getItemInfo() {
	idstr := getIDs(layouts)

	current_tick := time.Now().Unix()
	mysqlHelper := db.GetMysqlHelper()
	sql := "select id, type, start_tick, end_tick, weight, version_code, region, channel, clickable, action, args, router, pic, web_url, content, color from advert_oper_redesign where status = ? and id in"
	sql = fmt.Sprintf("%s (%s)", sql, idstr)
	log.Info("sql:%s",sql)
	results, err := mysqlHelper.Query(sql, EFFECT)
	//log.Info("results:%s",results)
	if err != nil {
		log.Warnf("sql err, getItemInfo, sql:%s, err:%s", sql, err.Error())
		return
	}
	if len(results) == 0 {
		return
	}
	for _, dt := range results {
		end_tick := dt["end_tick"].(int64)
		if end_tick <= current_tick {
			continue
		}
		id := dt["id"].(int64)
		itemType := dt["type"].(int64)
		switch itemType {
		case 1:
			{
				upItems[int(id)] = getText(dt)
			}
		case 2:
			{
				//upItems[int(id)] = getImg(dt)
				img := getImg(dt)
				if img.tag == -1 {
				} else {
					upItems[int(id)] = getImg(dt)
				}
			}
		case 3:
			{
				upItems[int(id)] = getWeb(dt)
			}
		case 4:
			{
				upItems[int(id)] = getJson(dt)
			}
		default:
		}
	}

	MyLock.Lock()
	items = upItems
	MyLock.Unlock()

	upItems = make(map[int]interface{})
}

func getMaxid() int64 {
	mysqlHelper := db.GetMysqlHelper()
	sql := `select max(id) as maxid from advert_oper_redesign`
	result, err := mysqlHelper.Query(sql)
	if err != nil {
		log.Warnf("sql err, getMaxid, sql:%s, err:%s", sql, err.Error())
		return int64(0)
	}
	if result[0]["maxid"] == nil {
		return int64(0)
	}
	idstr := string(result[0]["maxid"].([]byte))
	max, _ := strconv.Atoi(idstr)
	return int64(max)
}

func getIDs(layout map[string]LayoutSeq) string {
	mid := make([]string, 0)
	if len(layout) == 0 {
		return ""
	}
	for _, platInfo := range layout {
		if len(platInfo) == 0 {
			continue
		}
		for _, idstr := range platInfo {
			if idstr == "" {
				continue
			}
			mid = append(mid, idstr)
		}
	}
	return strings.Join(mid, ",")
}
